home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 231_01 / drive.c < prev    next >
Text File  |  1987-06-15  |  14KB  |  675 lines

  1. /*
  2.     Little Smalltalk
  3.         command parser
  4.  
  5.         timothy a. budd, 12/84
  6.  
  7. */
  8. /*
  9.     The source code for the Little Smalltalk System may be freely
  10.     copied provided that the source of all files is acknowledged
  11.     and that this condition is copied with each file.
  12.  
  13.     The Little Smalltalk System is distributed without responsibility
  14.     for the performance of the program and without any guarantee of
  15.     maintenance.
  16.  
  17.     All questions concerning Little Smalltalk should be addressed to:
  18.  
  19.         Professor Tim Budd
  20.         Department of Computer Science
  21.         Oregon State University
  22.         Corvallis, Oregon
  23.         97331
  24.         USA
  25. */
  26. # include <stdio.h>
  27. # include "object.h"
  28. # define DRIVECODE
  29. # include "drive.h"
  30. # include "cmds.h"
  31. # include "number.h"
  32. # include "symbol.h"
  33. # include "string.h"
  34. # include "byte.h"
  35. # include "interp.h"
  36. # include "primitive.h"
  37.  
  38. extern enum lextokens token, nextlex();
  39. extern int prntcmd;
  40. extern int inisstd;
  41. extern int started;
  42. extern char toktext[];
  43. extern char *lexptr;
  44. extern int line_grabber();
  45. extern tok_type t;
  46.  
  47. /* test_driver - see if the driver should be invoked */
  48. int test_driver(block)
  49. int block;    /* indicates wheter to use block or non-blocking input */
  50. {
  51.     switch(line_grabber( block )) {
  52.         default: cant_happen(17);
  53.         case -1:
  54.             /*  return end of file indication */
  55.             return(0);
  56.         case 0:
  57.             /* enqueue driver process again */
  58.             return(1);
  59.         case 1:
  60.             if (*lexptr == ')') {
  61.                 dolexcommand(lexptr);
  62.                 return(1);
  63.                 }
  64.             parse();
  65.             return(1);
  66.         }
  67. }
  68.  
  69. /* ---- code generation routines  -------------- */
  70. # define CODEMAX 500
  71. static uchar code[CODEMAX];
  72. static int codetop = 0;
  73.  
  74. static gencode(value)
  75. register int value;
  76. {
  77.     if (value >= 256)
  78.         lexerr("code word too big: %d", value);
  79.     if (codetop > CODEMAX)
  80.         lexerr("too many code words: %d", codetop);
  81.     /*if (started)
  82.     fprintf(stderr,"code %d (%d %d)\n", value, value/16, value%16);*/
  83.     code[codetop++] = itouc(value);
  84. }
  85.  
  86. static genhighlow(high, low)
  87. register int high;
  88. register int low;
  89. {
  90.     if (high < 0 || high > 16)
  91.         lexerr("genhighlow error: %d", high);
  92.     if (low < 0)
  93.         lexerr("genhighlow low error: %d", low);
  94.     if (low < 16) gencode(high * 16 + low);
  95.     else {
  96.         gencode(TWOBIT * 16 + high);
  97.         gencode(low);
  98.         }
  99. }
  100. /*-------------------------------------------------------*/
  101.  
  102. static int errflag;
  103.  
  104. /* parse - main parser */
  105. int parse()
  106. {    register int i;
  107.  
  108.     errflag = 0;
  109.     reset();
  110.  
  111.     if (nextlex() == nothing) return(1);
  112.     if (token == NL) return(1);
  113.  
  114.     i = aprimary();
  115.     if (i >= 0) {
  116.         asign(i);
  117.         if ((prntcmd > 1) && inisstd)
  118.             genhighlow(UNSEND, PRNTCMD);
  119.         }
  120.     else {
  121.         cexpression();
  122.         if (prntcmd && inisstd)
  123.             genhighlow(UNSEND, PRNTCMD);
  124.         }
  125.     genhighlow(POPINSTANCE, 0);    /* assign to ``last'' */
  126.     if (errflag)
  127.         return(1);
  128.     if (token == nothing || token == NL) {
  129.         bld_interpreter();
  130.         return(0);
  131.         }
  132.     expect("end of expression");
  133.     return(1);
  134. }
  135.  
  136. /* asign - code for an assignment statement - leaves result on stack */
  137. static asign(pos)
  138. int pos;
  139. {    int i;
  140.  
  141.     i = aprimary();
  142.     if (i >= 0) {
  143.         asign(i);
  144.         }
  145.     else {
  146.         cexpression();
  147.         }
  148.     genhighlow(SPECIAL, DUPSTACK);
  149.     genhighlow(POPINSTANCE, pos);
  150. }
  151.  
  152. /* expression - read an expression, leaving result on stack */
  153. static expression()
  154. {    int i;
  155.  
  156.     i = aprimary();
  157.     if (i >= 0) {
  158.         asign(i);
  159.         }
  160.     else {
  161.         cexpression();
  162.         }
  163. }
  164.  
  165. /* cexpression - code for a (possibly cascaded) expression */
  166. static cexpression()
  167. {
  168.     kcontinuation();
  169.     while (token == SEMI) {
  170.         genhighlow(SPECIAL, DUPSTACK);
  171.         nextlex();
  172.         kcontinuation();
  173.         genhighlow(SPECIAL, POPSTACK);
  174.         }
  175. }
  176.  
  177. /* kcontinuation - keyword continuation */
  178. static kcontinuation()
  179. {    char kbuf[150];
  180.     int  kcount;
  181.  
  182.     bcontinuation();
  183.     if (token == KEYWORD) {
  184.         kbuf[0] = '\0';
  185.         kcount = 0;
  186.         while (token == KEYWORD) {
  187.             strcat(kbuf, t.c);
  188.             strcat(kbuf, ":");
  189.             kcount++;
  190.             nextlex();
  191.             primary(1);
  192.             bcontinuation();
  193.             }
  194.         gensend(kbuf, kcount);
  195.         }
  196. }
  197.  
  198. /* isbinary - see if the current token(s) is a binary */
  199. static int isbinary(bbuf)
  200. char *bbuf;
  201. {
  202.     if (token == BINARY || token == MINUS ||
  203.         token == BAR || token == PE) {
  204.         strcpy(bbuf, t.c);
  205.         nextlex();
  206.         if (token == BINARY || token == MINUS ||
  207.                 token == BAR || token == PE) {
  208.             strcat(bbuf, t.c);
  209.             nextlex();
  210.             }
  211.         return(1);
  212.         }
  213.     return(0);
  214. }
  215.  
  216. /* bcontinuation - binary continuation */
  217. static bcontinuation()
  218. {    char bbuf[3];
  219.  
  220.     ucontinuation();
  221.     while (isbinary(bbuf)) {
  222.         primary(1);
  223.         ucontinuation();
  224.         gensend(bbuf, 1);
  225.         }
  226. }
  227.  
  228. /* ucontinuation - unary continuation */
  229. static ucontinuation()
  230. {
  231.     while (token == LOWERCASEVAR) {
  232.         gensend(t.c, 0);
  233.         nextlex();
  234.         }
  235. }
  236.  
  237. /* aprimary - primary or beginning of assignment */
  238. static int aprimary()
  239. {    char *c;
  240.  
  241.     if (token == LOWERCASEVAR) {
  242.         c = t.c;
  243.         if (nextlex() == ASSIGN) {
  244.             nextlex();
  245.             return(findvar(c, 1));
  246.             }
  247.         else {
  248.             genvar(c);
  249.             return( -1 );
  250.             }
  251.         }
  252.     primary(1);
  253.     return( - 1 );
  254. }
  255.  
  256. /* primary - find a primary expression */
  257. static int primary(must)
  258. int must;    /* must we find something ? */
  259. {    int i, count;
  260.  
  261.     switch(token) {
  262.         case UPPERCASEVAR:
  263.             genhighlow(PUSHCLASS, aliteral(1));
  264.             break;
  265.  
  266.         case LOWERCASEVAR:
  267.             genvar(t.c);
  268.             nextlex();
  269.             break;
  270.  
  271.         case LITNUM:
  272.             if (t.i >= 0 && t.i < 10) {
  273.                 genhighlow(PUSHSPECIAL, t.i);
  274.                 nextlex();
  275.                 }
  276.             else {
  277.                 genhighlow(PUSHLIT, aliteral(1));
  278.                 }
  279.             break;
  280.  
  281.         case MINUS:
  282.         case LITFNUM:
  283.         case LITCHAR:
  284.         case LITSTR:
  285.         case LITSYM:
  286.         case PS:
  287.             genhighlow(PUSHLIT, aliteral(1));
  288.             break;
  289.  
  290.         case PSEUDO:
  291.             switch(t.p) {
  292.                 case nilvar: i = 13; break;
  293.                 case truevar: i = 11; break;
  294.                 case falsevar: i = 12; break;
  295.                 case smallvar: i  = 14; break;
  296.                 default: lexerr("unknown pseudo var %d", t.p);
  297.                 }
  298.             genhighlow(PUSHSPECIAL, i);
  299.             nextlex();
  300.             break;
  301.  
  302.         case PRIMITIVE:
  303.             if (nextlex() != LITNUM) expect("primitive number");
  304.             i = t.i;
  305.             nextlex();
  306.             count = 0;
  307.             while (primary(0)) count++;
  308.             if (token != PE) expect("primitive end");
  309.             nextlex();
  310.             genhighlow(SPECIAL, PRIMCMD);
  311.             gencode(count);
  312.             gencode(i);
  313.             break;
  314.  
  315.         case LP:
  316.             nextlex();
  317.             expression();
  318.             if (token != RP) expect("right parenthesis");
  319.             nextlex();
  320.             break;
  321.  
  322.         case LB:
  323.             nextlex();
  324.             block();
  325.             break;
  326.  
  327.         default:
  328.             if (must) expect("primary expression");
  329.             return(0);
  330.         }
  331.     return(1);
  332. }
  333.  
  334. static int maxtemps = 1;
  335. static int temptop = 0;
  336. static char *tempnames[20];
  337.  
  338. /* block - parse a block definition */
  339. static block()
  340. {    int count, i, position;
  341.  
  342.     count = 0;
  343.     if (token == COLONVAR) {
  344.         while (token == COLONVAR) {
  345.             tempnames[temptop++] = t.c;
  346.             if (temptop > maxtemps) maxtemps = temptop;
  347.             count++;
  348.             nextlex();
  349.             }
  350.         if (token != BAR)
  351.             expect("bar following arguments in block");
  352.         nextlex();
  353.         }
  354.     genhighlow(BLOCKCREATE, count);
  355.     if (count)         /* where arguments go in context */
  356.         gencode(1 + (temptop - count));    
  357.     position = codetop;
  358.     gencode(0);
  359.  
  360.     if (token == RB) {
  361.         genhighlow(PUSHSPECIAL, 13);
  362.         }
  363.     else
  364.         while (1) {
  365.             i = aprimary();
  366.             if (i >= 0) {
  367.                 expression();
  368.                 if (token != PERIOD)
  369.                     genhighlow(SPECIAL, DUPSTACK);
  370.                 genhighlow(POPINSTANCE, i);
  371.                 }
  372.             else {
  373.                 cexpression();
  374.                 if (token == PERIOD)
  375.                     genhighlow(SPECIAL, POPSTACK);
  376.                 }
  377.             if (token != PERIOD)
  378.                 break;
  379.             nextlex();
  380.             }
  381.     genhighlow(SPECIAL, RETURN);
  382.     if (token != RB) expect("end of block");
  383.     temptop -= count;
  384.     nextlex();
  385.     i = (codetop - position) - 1;
  386.     if (i > 255)
  387.         lexerr("block too big %d", i);
  388.     code[position] = itouc(i);
  389. }
  390.  
  391. # define LITMAX 100
  392. static object *lit_array[LITMAX];
  393. static int littop = 0;
  394.  
  395. static int addliteral(lit)
  396. object *lit;
  397. {
  398.     if (littop >= LITMAX)
  399.         cant_happen(18);
  400.     sassign(lit_array[littop++], lit);
  401.     return(littop - 1);
  402. }
  403.  
  404. /* aliteral - find a literal that is part of a literal array */
  405. static int aliteral(must)
  406. int must;    /* must we find something ? */
  407. {    char *c;
  408.     object *new;
  409.     int count;
  410.     int bytetop;
  411.     uchar bytes[200];
  412.  
  413.     switch(token) {
  414.         case MIN